/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.registration.business.security.boundary;

import it.polimi.registration.business.security.entity.Event;
import it.polimi.registration.business.security.entity.SystemNotification;
import it.polimi.registration.business.security.entity.User;
import java.io.IOException;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import net.aksingh.owmjapis.AbstractWeather.Weather;
import net.aksingh.owmjapis.DailyForecast;
import net.aksingh.owmjapis.HourlyForecast;
import net.aksingh.owmjapis.HourlyForecast.Forecast;
import net.aksingh.owmjapis.OpenWeatherMap;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.json.JSONException;


/**
 *
 * @author Stefano
 */
@Stateless
public class WeatherService {
    
    @PersistenceContext
    EntityManager em;
    
    @EJB
    private SystemNotificationManager sm;
    
    @EJB
    private InviteManager im;
    
    @EJB
    private UserManager um;
    
    @EJB
    private EventManager EM;
        
    private boolean good;
    private String description;
    private SystemNotification systemNotification;
    private Date nextsunnyday;
    private int weathercode;
    
    public int weatherService (String city, Date date)
            throws IOException, MalformedURLException, JSONException {
        
       
        
        OpenWeatherMap owm = new OpenWeatherMap("9722c3165e338fc70a02ac9039e91e00");

        HourlyForecast hourlyForecast = owm.hourlyForecastByCityName(city);
        
        boolean found = false;
        
        if(date.after(Calendar.getInstance().getTime())){
            if(hourlyForecast.hasForecastCount()){                
                for (int i=0; i<hourlyForecast.getForecastCount(); i++){
                    Forecast forecast = hourlyForecast.getForecastInstance(i);
                    if(forecast.getDateTime().after(date) && found==false){
                        found=true;                        
                        Weather weather = forecast.getWeatherInstance(0);
                        return weather.getWeatherCode();
                        
                    }
                }
            }
        }
        
        return 963; 
    
}
    
    public boolean weatherService2 (String city,String giorni)
            throws IOException, MalformedURLException, JSONException {
        
       
        boolean esci=FALSE;
        OpenWeatherMap owm2 = new OpenWeatherMap("9722c3165e338fc70a02ac9039e91e00");
        
        DailyForecast dailyForecastByCityName= owm2.dailyForecastByCityName(city,Byte.parseByte(giorni) );
        if(dailyForecastByCityName!=null)
        {
        int i,j;
        for(i=0;i<dailyForecastByCityName.getForecastCount()&&esci==FALSE;i++)
        {
            for(j=0;j<dailyForecastByCityName.getForecastInstance(i).getWeatherCount()&& esci==FALSE;j++)
            {
                    WeatherCheck(dailyForecastByCityName.getForecastInstance(i).getWeatherInstance(j).getWeatherCode());
                    if(this.good)
                    {
                        esci=TRUE;
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(dailyForecastByCityName.getForecastInstance(i).getDateTime());
                        nextsunnyday=dailyForecastByCityName.getForecastInstance(i).getDateTime();
                        weathercode=dailyForecastByCityName.getForecastInstance(i).getWeatherInstance(j).getWeatherCode();
                        return esci;
                    }
                }          
            } 
        nextsunnyday=null;
        }
        else
        {
        System.out.println("ho ricevuto risposta nulla eccezione");
        return esci;
        }
    return esci;
}
    
    
public void WeatherCheck(int cond)
{
    switch(cond)
    {
        case 200: 
                good=FALSE; 
                description="thunderstorm with light rain";
            break;
        case 201: 
                good=FALSE; 
                description="thunderstorm with rain";
            break;
        case 202: 
                good=FALSE; 
                description="thunderstorm with heavy rain";
            break;
        case 210: 
                good=FALSE; 
                description="light thunderstorm";
            break;
        case 211: 
                good=FALSE; 
                description="thunderstorm";
            break;
        case 212: 
                good=FALSE; 
                description="heavy thunderstorm";
            break;
        case 221: 
                good=FALSE; 
                description="ragged thunderstorm";
            break;
        case 230: 
                good=FALSE; 
                description="thunderstorm with light drizzle";
            break;
        case 231: 
                good=FALSE; 
                description="thunderstorm with drizzle";
            break;
        case 232: 
                good=FALSE; 
                description="thunderstorm with heavy drizzle";
            break;
        case 300: 
                good=FALSE; 
                description="light intensity drizzle";
            break;
        case 301: 
                good=FALSE; 
                description="drizzle";
            break;
        case 302: 
                good=FALSE; 
                description="heavy intensity drizzle";
            break;
        case 310: 
                good=FALSE; 
                description="light intensity drizzle rain";
            break;
        case 311: 
                good=FALSE; 
                description="drizzle rain";
            break;
        case 312: 
                good=FALSE; 
                description="heavy intensity drizzle rain";
            break;
        case 313: 
                good=FALSE; 
                description="shower rain and drizzle";
            break;
        case 314: 
                good=FALSE; 
                description="heavy shower rain and drizzle";
            break;
        case 321: 
                good=FALSE; 
                description="shower drizzle";
            break;
        case 500: 
                good=FALSE; 
                description="light rain";
            break;
        case 501: 
                good=FALSE; 
                description="moderate rain";
            break;
        case 502: 
                good=FALSE; 
                description="heavy intensity rain";
            break;
        case 503: 
                good=FALSE; 
                description="very heavy rain";
            break;
        case 504: 
                good=FALSE; 
                description="extreme rain";
            break;
        case 511: 
                good=FALSE; 
                description="freezing rain";
            break;
        case 520: 
                good=FALSE; 
                description="light intensity shower rain";
            break;
        case 521: 
                good=FALSE; 
                description="shower rain";
            break;
        case 522: 
                good=FALSE; 
                description="heavy intensity shower rain";
            break;
        case 531: 
                good=FALSE; 
                description="ragged shower rain";
            break;
        case 600: 
                good=FALSE; 
                description="light snow";
            break;
        case 601: 
                good=FALSE; 
                description="snow";
            break;
        case 602: 
                good=FALSE; 
                description="heavy snow";
            break;
        case 611: 
                good=FALSE; 
                description="sleet";
            break;
        case 612: 
                good=FALSE; 
                description="shower sleet";
            break;
        case 615: 
                good=FALSE; 
                description="light rain and snow";
            break;
        case 616: 
                good=FALSE; 
                description="rain and snow";
            break;
        case 620: 
                good=FALSE; 
                description="light shower snow";
            break;
        case 621: 
                good=FALSE; 
                description="shower snow";
            break;
        case 622: 
                good=FALSE; 
                description="heavy shower snow";
            break;
        case 701: 
                good=FALSE; 
                description="mist";
            break;
        case 711: 
                good=FALSE; 
                description="smoke";
            break;
        case 721: 
                good=FALSE; 
                description="haze";
            break;
        case 731: 
                good=FALSE; 
                description="sand, dust whirls";
            break;
        case 741: 
                good=FALSE; 
                description="fog";
            break;
        case 751: 
                good=FALSE; 
                description="sand";
            break;
        case 761: 
                good=FALSE; 
                description="dust";
            break;
        case 762: 
                good=FALSE; 
                description="volcanic ash";
            break;
        case 771: 
                good=FALSE; 
                description="squalls";
            break;
        case 781: 
                good=FALSE; 
                description="tornado";
            break;
        case 800: 
                good=TRUE; 
                description="clear sky";
            break;
        case 801: 
                good=TRUE; 
                description="few clouds";
            break;
        case 802: 
                good=TRUE; 
                description="scattered clouds";
            break;
        case 803: 
                good=TRUE; 
                description="broken clouds";
            break;
        case 804: 
                good=TRUE; 
                description="overcast clouds";
            break;
        case 900: 
                good=FALSE; 
                description="tornado";
            break;
        case 901: 
                good=FALSE; 
                description="tropical storm";
            break;
        case 902: 
                good=FALSE; 
                description="hurricane";
            break;
        case 903: 
                good=FALSE; 
                description="cold";
            break;
        case 904: 
                good=TRUE; 
                description="hot";
            break;
        case 905: 
                good=FALSE; 
                description="windy";
            break;
        case 906: 
                good=FALSE; 
                description="hail";
            break;
        case 951: 
                good=TRUE; 
                description="calm";
            break;
        case 952: 
                good=TRUE; 
                description="light breeze";
            break;
        case 953: 
                good=TRUE; 
                description="gentle breeze";
            break;
        case 954: 
                good=TRUE; 
                description="moderate breeze";
            break;
        case 955: 
                good=TRUE; 
                description="fresh breeze";
            break;
        case 956: 
                good=FALSE; 
                description="strong breeze";
            break;
        case 957: 
                good=FALSE; 
                description="high wind, near gale";
            break;
        case 958: 
                good=FALSE; 
                description="gale";
            break;
        case 959: 
                good=FALSE; 
                description="severe gale";
            break;
        case 960: 
                good=FALSE; 
                description="storm";
            break;
        case 961: 
                good=FALSE; 
                description="violent storm";
            break;
        case 962: 
                good=FALSE; 
                description="hurricane";
            break;
        case 963:
                good=TRUE;
                description="Not Available";
            break;
        default:
                good=TRUE;
                description="good time";
            break;
    }
}


public boolean getgood()
{
    return good;
}
public String getdescription()
{
    return description;
}

public void checkWeatherEvent(Event value) throws IOException{
        Event event=EM.getEvent(value.getId());
        Date today;
        today = Calendar.getInstance().getTime();
        int days = Days.daysBetween(new DateTime(today), new DateTime(event.getStartTime().getTime())).getDays();
        days = days + 1;
        WeatherCheck(event.getWeatherCondition());//aggiorno i booleani della classe per capire se ho ricevuto buono o cattivo tempo
        boolean goodWeather = this.good;
        /*
        SystemNotification sn=null;
        TypedQuery<SystemNotification> query = em.createQuery("SELECT e FROM SystemNotification e Where e.event = :event AND e.username = :user AND e.unread=:letta", SystemNotification.class);
                query.setParameter("event",event);
                query.setParameter("user",um.getLoggedUser());
                query.setParameter("letta", TRUE);
            try{
                sn=query.getSingleResult();
                }
            catch(NoResultException nre)
            {
              System.out.println("ECCEZIONE: nessuna notifica di sistema per questo utente "+um.getLoggedUser().getName());  
            }    
        if(sn==null)
        {*/
            System.out.println("la mia systemnotification dell'utente:"+um.getLoggedUser().getName()+ " è vuota e creo una notifica se nelle condizioni sotto sono ok");
        List<SystemNotification> notification = new ArrayList();
        notification = sm.getNotification(event, um.getLoggedUser());
        System.out.println("sto facendo check del tempo per "+event.getTitle());
        if (notification.isEmpty()){
            System.out.println("controllo se sn meno di 33 gg prima ma almeno maggiore di zero");
            System.out.println("controllo: days:"+days+" goodweather"+ goodWeather+" outdoor:"+event.getOutdoor()+" creator:"+event.getCreator());
            User logged=um.getLoggedUser();
            boolean creatore=FALSE;
            if(logged.getEmail()==event.getCreator().getEmail())
            {
                creatore=TRUE;
            }
            if(days<=3 && days>0 && !goodWeather && event.getOutdoor()==true && creatore)
            {  
                System.out.println("creatore evento sono nella condizione allora cerco il prossimo giorno bello tra 16 giorni");
                systemNotification = new SystemNotification(event.getCreator(),event);
                Calendar c=Calendar.getInstance();
                if(weatherService2(event.getLocation(),"16"))
                {
                System.out.println("trovato prossimo giorno bello:"+this.nextsunnyday);    
                c.setTime(this.nextsunnyday);
                } 
                systemNotification.setnextSunny(c);
                systemNotification.setweatherCode(this.weathercode);
                //imposto il nuovo sunny day e metti booleano per la visualizzazione se trovato o no 
                sm.save(systemNotification);            
            }
            if(days<=1 && days>0 && !goodWeather && event.getOutdoor()==true){
                List<User> participants = im.findParticipants(event);
                for(User user : participants){
                    systemNotification = new SystemNotification(user,event);
                sm.save(systemNotification);
                }
            }
        }
    }
}
        
        
    

